﻿<#
.SYNOPSIS
JACMOTORS App 图形化安装程序
.Code By YuBo (GUI版本) - 增加了类型颜色区分和控制台输出功能
#>

# 确保在GUI应用中显示控制台窗口，用于输出调试信息
Add-Type -Name ConsoleUtils -Namespace Win32 -MemberDefinition @'
[DllImport("kernel32.dll")]
public static extern bool AllocConsole();
[DllImport("kernel32.dll")]
public static extern bool FreeConsole();
'@
[Win32.ConsoleUtils]::AllocConsole() | Out-Null

# 加载Windows.Forms
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

# 创建20种不同的字体颜色用于分类显示
$categoryColors = @(
    [System.Drawing.Color]::FromArgb(0, 0, 139),    # 深海军蓝
    [System.Drawing.Color]::FromArgb(139, 0, 0),    # 深红色
    [System.Drawing.Color]::FromArgb(0, 100, 0),    # 深绿色
    [System.Drawing.Color]::FromArgb(148, 0, 211),  # 深紫色
    [System.Drawing.Color]::FromArgb(255, 140, 0),  # 暗橙色
    [System.Drawing.Color]::FromArgb(75, 0, 130),   # 靛蓝色
    [System.Drawing.Color]::FromArgb(128, 0, 0),    # 栗色
    [System.Drawing.Color]::FromArgb(0, 128, 0),    # 绿色
    [System.Drawing.Color]::FromArgb(0, 0, 128),    # 海军蓝
    [System.Drawing.Color]::FromArgb(128, 0, 128),  # 紫色
    [System.Drawing.Color]::FromArgb(128, 128, 0),  # 橄榄色
    [System.Drawing.Color]::FromArgb(0, 128, 128),  # 青色
    [System.Drawing.Color]::FromArgb(255, 0, 0),    # 红色
    [System.Drawing.Color]::FromArgb(0, 255, 0),    # Lime
    [System.Drawing.Color]::FromArgb(0, 0, 255),    # 蓝色
    [System.Drawing.Color]::FromArgb(255, 0, 255),  # 洋红色
    [System.Drawing.Color]::FromArgb(255, 255, 0),  # 黄色
    [System.Drawing.Color]::FromArgb(0, 255, 255),  # 青色
    [System.Drawing.Color]::FromArgb(165, 42, 42),  # 棕色
    [System.Drawing.Color]::FromArgb(128, 128, 128) # 灰色
)

# 存储分类与颜色的映射关系
$categoryToColor = @{}

# 创建主窗口
$form = New-Object System.Windows.Forms.Form
$form.Text = "JACMOTORS App 安装程序 2025-8-6（Code By YuBo）"
$form.Size = New-Object System.Drawing.Size(1000, 650)
$form.StartPosition = "CenterScreen"
$form.FormBorderStyle = "FixedDialog"
$form.MaximizeBox = $false

# 添加背景图片（增强调试版）
$backgroundImagePath = Join-Path -Path $PSScriptRoot -ChildPath "background.jpg"
Write-Host "`n===== 背景图片加载调试 =====" -ForegroundColor Cyan
Write-Host "脚本所在目录: $PSScriptRoot" -ForegroundColor Cyan
Write-Host "尝试加载的图片路径: $backgroundImagePath" -ForegroundColor Cyan

if (Test-Path $backgroundImagePath) {
    Write-Host "图片文件存在，尝试加载..." -ForegroundColor Green
    try {
        # 检查文件是否为有效的图片
        $fileInfo = New-Object System.IO.FileInfo($backgroundImagePath)
        Write-Host "文件大小: $($fileInfo.Length) 字节" -ForegroundColor Cyan
        
        # 尝试加载图片
        $form.BackgroundImage = [System.Drawing.Image]::FromFile($backgroundImagePath)
        $form.BackgroundImageLayout = [System.Windows.Forms.ImageLayout]::Stretch
        Write-Host "图片加载成功！" -ForegroundColor Green
    }
    catch {
        Write-Host "图片加载失败: $_" -ForegroundColor Red
        Write-Host "可能原因: 图片损坏、格式不支持或权限不足" -ForegroundColor Yellow
        $form.BackColor = [System.Drawing.Color]::White
    }
}
else {
    Write-Host "未找到背景图片！" -ForegroundColor Red
    Write-Host "请确保在脚本目录下放置名为 'background.jpg' 的图片文件" -ForegroundColor Yellow
    $form.BackColor = [System.Drawing.Color]::White
}
Write-Host "==========================`n" -ForegroundColor Cyan

# 窗口关闭事件，释放控制台和图片资源
$form.Add_FormClosing({
    [Win32.ConsoleUtils]::FreeConsole() | Out-Null
    if ($form.BackgroundImage) {
        $form.BackgroundImage.Dispose()
    }
})

# 创建完全透明面板作为背景容器（移除半透明效果）
$backgroundPanel = New-Object System.Windows.Forms.Panel
$backgroundPanel.Dock = [System.Windows.Forms.DockStyle]::Fill
$backgroundPanel.BackColor = [System.Drawing.Color]::FromArgb(0, 255, 255, 255) # 完全透明
$form.Controls.Add($backgroundPanel)

# 确保背景图片显示在最底层
$form.SendToBack()

# 创建标题标签（初始隐藏）- 设置为红色字体
$titleLabel = New-Object System.Windows.Forms.Label
$titleLabel.Text = "请选择您要安装的软件，可输入关键字进行筛选，也可以根据分类进行筛选，支持多选批量安装！"
$titleLabel.Font = New-Object System.Drawing.Font("微软雅黑", 12, [System.Drawing.FontStyle]::Bold)
$titleLabel.ForeColor = [System.Drawing.Color]::Red  # 红色字体
$titleLabel.Location = New-Object System.Drawing.Point(20, 10)
$titleLabel.Size = New-Object System.Drawing.Size(960, 30)
$titleLabel.TextAlign = [System.Drawing.ContentAlignment]::MiddleCenter
$titleLabel.BackColor = [System.Drawing.Color]::Transparent
$titleLabel.Visible = $false  # 初始隐藏
$backgroundPanel.Controls.Add($titleLabel)

# 顶部搜索区域布局（初始隐藏）
$searchPanel = New-Object System.Windows.Forms.Panel
$searchPanel.Location = New-Object System.Drawing.Point(20, 50)
$searchPanel.Size = New-Object System.Drawing.Size(940, 40)
$searchPanel.BackColor = [System.Drawing.Color]::FromArgb(0, 255, 255, 255) # 完全透明
$searchPanel.Visible = $false  # 初始隐藏
$backgroundPanel.Controls.Add($searchPanel)

# 搜索过滤文本框（默认值为*）
$searchTextBox = New-Object System.Windows.Forms.TextBox
$searchTextBox.Location = New-Object System.Drawing.Point(10, 5)
$searchTextBox.Size = New-Object System.Drawing.Size(300, 25)
$searchTextBox.Font = New-Object System.Drawing.Font("微软雅黑", 9)
$searchTextBox.Text = "*"  # 默认搜索值为*（匹配所有）
$searchTextBox.ForeColor = [System.Drawing.Color]::Black

# 进入事件：清空默认值
$searchTextBox.Add_Enter({
    if ($this.Text -eq "*") {
        $this.Text = ""
    }
})

# 离开事件：恢复默认值（内容为空时）
$searchTextBox.Add_Leave({
    if ([string]::IsNullOrEmpty($this.Text)) {
        $this.Text = "*"
    }
})
$searchPanel.Controls.Add($searchTextBox)

# 创建全选按钮（直接添加到搜索面板）- 改为粉色
$selectAllButton = New-Object System.Windows.Forms.Button
$selectAllButton.Text = "[全选]"
$selectAllButton.Location = New-Object System.Drawing.Point(330, 5)  # 位于搜索框右侧
$selectAllButton.Size = New-Object System.Drawing.Size(100, 30)
$selectAllButton.Font = New-Object System.Drawing.Font("微软雅黑", 9)
$selectAllButton.BackColor = [System.Drawing.Color]::FromArgb(255, 192, 203)  # 粉色
$selectAllButton.ForeColor = [System.Drawing.Color]::Black
$searchPanel.Controls.Add($selectAllButton)

# 创建取消全选按钮（直接添加到搜索面板）- 改为黄色
$unselectAllButton = New-Object System.Windows.Forms.Button
$unselectAllButton.Text = "[取消]"
$unselectAllButton.Location = New-Object System.Drawing.Point(450, 5)  # 位于全选按钮右侧
$unselectAllButton.Size = New-Object System.Drawing.Size(100, 30)
$unselectAllButton.Font = New-Object System.Drawing.Font("微软雅黑", 9)
$unselectAllButton.BackColor = [System.Drawing.Color]::Yellow  # 黄色
$unselectAllButton.ForeColor = [System.Drawing.Color]::Black
$searchPanel.Controls.Add($unselectAllButton)

# 添加WhatsApp更新按钮 - 红色
$whatsappButton = New-Object System.Windows.Forms.Button
$whatsappButton.Text = "[安装更新WhatsApp]"
$whatsappButton.Location = New-Object System.Drawing.Point(570, 5)  # 位于取消全选按钮右侧
$whatsappButton.Size = New-Object System.Drawing.Size(150, 30)
$whatsappButton.Font = New-Object System.Drawing.Font("微软雅黑", 9, [System.Drawing.FontStyle]::Bold)
$whatsappButton.BackColor = [System.Drawing.Color]::Red  # 红色背景
$whatsappButton.ForeColor = [System.Drawing.Color]::White  # 白色文字
$whatsappButton.Add_Click({
    # 执行WhatsApp.ps1脚本（与当前脚本同目录）
    $scriptPath = Join-Path -Path $PSScriptRoot -ChildPath "WhatsApp.ps1"
    if (Test-Path $scriptPath) {
        # 显示日志窗口并记录操作
        $rightPanel.Visible = $true
        $tabControl.Size = New-Object System.Drawing.Size(550, 450)
        Add-Log "正在新窗口执行WhatsApp.ps1脚本..."
        
        # 同时输出到控制台
        Write-Host "[$(Get-Date -Format 'HH:mm:ss')] 正在新窗口执行WhatsApp.ps1脚本..." -ForegroundColor Cyan
        
        # 打开新的PowerShell窗口执行脚本，脚本执行完毕后自动关闭窗口
        Start-Process powershell.exe -ArgumentList "-ExecutionPolicy Bypass -File `"$scriptPath`""
        
        Add-Log "已在新窗口启动WhatsApp.ps1安装..."
        Write-Host "[$(Get-Date -Format 'HH:mm:ss')] 已在新窗口启动WhatsApp.ps1安装..." -ForegroundColor Cyan
    }
    else {
        $warningMsg = "未找到WhatsApp.ps1脚本，路径: $scriptPath"
        Add-Log $warningMsg
        Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $warningMsg" -ForegroundColor Red
        [System.Windows.Forms.MessageBox]::Show($warningMsg, "警告", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Warning)
    }
})

$searchPanel.Controls.Add($whatsappButton)

# 分类选项卡控件 - 调整宽度，因为日志面板默认隐藏（初始隐藏）
$tabControl = New-Object System.Windows.Forms.TabControl
$tabControl.Location = New-Object System.Drawing.Point(20, 100)
$tabControl.Size = New-Object System.Drawing.Size(940, 450)  # 初始宽度更大，占据整个空间
$tabControl.Font = New-Object System.Drawing.Font("微软雅黑", 9, [System.Drawing.FontStyle]::Bold)  # 选项卡标题加粗
$tabControl.Multiline = $true
$tabControl.Visible = $false  # 初始隐藏
$backgroundPanel.Controls.Add($tabControl)

# 右侧操作日志区域布局 - 默认隐藏
$rightPanel = New-Object System.Windows.Forms.Panel
$rightPanel.Location = New-Object System.Drawing.Point(590, 100)
$rightPanel.Size = New-Object System.Drawing.Size(370, 450)
$rightPanel.Visible = $false  # 日志面板默认隐藏
$rightPanel.BackColor = [System.Drawing.Color]::FromArgb(0, 255, 255, 255) # 完全透明
$backgroundPanel.Controls.Add($rightPanel)

# 日志标题（右侧）
$logTitleLabel = New-Object System.Windows.Forms.Label
$logTitleLabel.Text = "操作日志"
$logTitleLabel.Font = New-Object System.Drawing.Font("微软雅黑", 9, [System.Drawing.FontStyle]::Bold)
$logTitleLabel.Location = New-Object System.Drawing.Point(0, 0)
$logTitleLabel.Size = New-Object System.Drawing.Size(370, 20)
$rightPanel.Controls.Add($logTitleLabel)

# 日志文本框（右侧）
$logTextBox = New-Object System.Windows.Forms.TextBox
$logTextBox.Location = New-Object System.Drawing.Point(0, 30)
$logTextBox.Size = New-Object System.Drawing.Size(370, 420)
$logTextBox.Font = New-Object System.Drawing.Font("Consolas", 9)
$logTextBox.Multiline = $true
$logTextBox.ReadOnly = $true
$logTextBox.ScrollBars = [System.Windows.Forms.ScrollBars]::Vertical
$rightPanel.Controls.Add($logTextBox)

# 创建开始安装(WinGet通道)按钮（初始隐藏）
$installButton = New-Object System.Windows.Forms.Button
$installButton.Text = "[自动安装](WinGet)"
$installButton.Location = New-Object System.Drawing.Point(250, 560)
$installButton.Size = New-Object System.Drawing.Size(150, 30)
$installButton.Font = New-Object System.Drawing.Font("微软雅黑", 9, [System.Drawing.FontStyle]::Bold)
$installButton.BackColor = [System.Drawing.Color]::FromArgb(76, 175, 80)
$installButton.ForeColor = [System.Drawing.Color]::White
$installButton.Visible = $false  # 初始隐藏
$backgroundPanel.Controls.Add($installButton)

# 创建开始下载(多线程)按钮 - 紫色（初始隐藏）
$multiThreadInstallButton = New-Object System.Windows.Forms.Button
$multiThreadInstallButton.Text = "[手动安装](Aira2)"
$multiThreadInstallButton.Location = New-Object System.Drawing.Point(420, 560)
$multiThreadInstallButton.Size = New-Object System.Drawing.Size(150, 30)
$multiThreadInstallButton.Font = New-Object System.Drawing.Font("微软雅黑", 9, [System.Drawing.FontStyle]::Bold)
$multiThreadInstallButton.BackColor = [System.Drawing.Color]::FromArgb(148, 0, 211)  # 深紫色
$multiThreadInstallButton.ForeColor = [System.Drawing.Color]::White
$multiThreadInstallButton.Visible = $false  # 初始隐藏
$backgroundPanel.Controls.Add($multiThreadInstallButton)

# 创建退出安装按钮 - 改为蓝色（初始隐藏）
$exitButton = New-Object System.Windows.Forms.Button
$exitButton.Text = "[退出安装]"
$exitButton.Location = New-Object System.Drawing.Point(580, 560)
$exitButton.Size = New-Object System.Drawing.Size(150, 30)
$exitButton.Font = New-Object System.Drawing.Font("微软雅黑", 9)
$exitButton.BackColor = [System.Drawing.Color]::FromArgb(0, 123, 255)  # 蓝色
$exitButton.ForeColor = [System.Drawing.Color]::White
$exitButton.Visible = $false  # 初始隐藏
$backgroundPanel.Controls.Add($exitButton)

# 定义配置文件路径（与脚本在同一目录）
$scriptPath = $MyInvocation.MyCommand.Definition  # 获取当前脚本的完整路径（包括文件名）
$scriptDir = Split-Path -Parent $scriptPath       # 提取脚本所在的目录路径
$iniFile = Join-Path -Path $scriptDir -ChildPath "soft.ini"  # 拼接配置文件的完整路径

# 存储应用程序信息的数组（包含分类）
$apps = @()
$categoryCheckLists = @{}  # 存储每个分类对应的复选框列表
$categoryFonts = @{}       # 存储每个分类对应的字体

# 日志记录函数 - 同时输出到日志窗口和控制台
function Add-Log {
    param([string]$message)
    $timeStamp = Get-Date -Format "HH:mm:ss"
    $logEntry = "[$timeStamp] $message"
    
    # 输出到日志窗口
    $logTextBox.AppendText("$logEntry`r`n")
    $logTextBox.ScrollToCaret()
    
    # 输出到控制台（不重复输出，如果是从控制台调用的）
    if (-not $MyInvocation.CommandOrigin -eq 'Runspace') {
        Write-Host $logEntry
    }
}

# 检查必要文件并加载应用列表、分类
try {
    # 初始化阶段输出到控制台
    Write-Host "[$(Get-Date -Format 'HH:mm:ss')] 开始初始化安装程序..." -ForegroundColor Cyan
    
    # 检查配置文件
    if (-not (Test-Path -Path $iniFile -PathType Leaf)) {
        throw "未找到配置文件 '$iniFile'。请确保它在脚本同目录。"
    }

    Write-Host "[$(Get-Date -Format 'HH:mm:ss')] 找到配置文件: $iniFile" -ForegroundColor Green

    # 读取并解析INI文件（格式：应用ID,中文名称,用途,分类）
    $lines = Get-Content $iniFile -Encoding UTF8 | Where-Object { $_ -match '\S' -and $_ -notmatch '^;' }

    # 验证标题行
    $header = $lines[0].Trim()
    if ($header -ne "应用ID,中文名称,用途,分类") {
        throw "配置文件格式不正确，第一行应为: 应用ID,中文名称,用途,分类"
    }

    # 创建"全部分类"选项卡 - 使用默认颜色
    $allTabPage = New-Object System.Windows.Forms.TabPage
    $allTabPage.Text = "全部分类"
    $allTabPage.BackColor = [System.Drawing.Color]::FromArgb(0, 255, 255, 255)  # 完全透明
    $allTabPage.ForeColor = [System.Drawing.Color]::Black  # 全部分类使用黑色
    
    $allCheckList = New-Object System.Windows.Forms.CheckedListBox
    $allCheckList.Dock = [System.Windows.Forms.DockStyle]::Fill
    $allCheckList.Font = New-Object System.Drawing.Font("微软雅黑", 9)
    $allCheckList.ForeColor = [System.Drawing.Color]::Black  # 全部分类使用黑色
    $allCheckList.CheckOnClick = $true
    $allTabPage.Controls.Add($allCheckList)
    $tabControl.Controls.Add($allTabPage)
    $categoryCheckLists["全部分类"] = $allCheckList
    $categoryToColor["全部分类"] = [System.Drawing.Color]::Black
    $categoryFonts["全部分类"] = $allCheckList.Font

    # 解析应用列表并添加到对应分类选项卡
    $allCategories = @()
    for ($i = 1; $i -lt $lines.Count; $i++) {
        $originalLine = $lines[$i]
        $line = $originalLine.Trim()
        
        # 改进的解析逻辑：处理描述中包含逗号的情况
        $parts = $line -split ','
        if ($parts.Count -ge 4) {
            # 提取确定的字段
            $appId = $parts[0].Trim()
            $name = $parts[1].Trim()
            $category = $parts[-1].Trim()
            
            # 合并中间部分作为描述（处理描述中包含逗号的情况）
            $descParts = $parts[2..($parts.Count - 2)]
            $desc = $descParts -join ',' -replace '^[\s,]+|[\s,]+$', ''  # 清理首尾空格和逗号
            
            $app = [PSCustomObject]@{
                Index    = $i
                AppId    = $appId
                Name     = $name
                Desc     = $desc
                Category = $category
            }
            $apps += $app

            # 添加到全部分类
            $displayText = "$($app.Name),$($app.Desc)"
            $allCheckList.Items.Add($displayText) | Out-Null

            # 检查是否需要创建新分类选项卡
            if ($allCategories -notcontains $app.Category) {
                $allCategories += $app.Category
                
                # 为新分类分配颜色（循环使用预定义的20种颜色）
                $colorIndex = ($allCategories.IndexOf($app.Category)) % $categoryColors.Count
                $categoryColor = $categoryColors[$colorIndex]
                $categoryToColor[$app.Category] = $categoryColor

                # 创建分类选项卡
                $tabPage = New-Object System.Windows.Forms.TabPage
                $tabPage.Text = $app.Category
                $tabPage.BackColor = [System.Drawing.Color]::FromArgb(0, 255, 255, 255)  # 完全透明
                $tabPage.ForeColor = $categoryColor  # 设置选项卡标题颜色
                
                # 创建列表框并设置字体颜色
                $checkList = New-Object System.Windows.Forms.CheckedListBox
                $checkList.Dock = [System.Windows.Forms.DockStyle]::Fill
                $checkList.Font = New-Object System.Drawing.Font("微软雅黑", 9)
                $checkList.ForeColor = $categoryColor  # 设置列表项字体颜色
                $checkList.CheckOnClick = $true
                $tabPage.Controls.Add($checkList)
                $tabControl.Controls.Add($tabPage)

                $categoryCheckLists[$app.Category] = $checkList
                $categoryFonts[$app.Category] = $checkList.Font
            }

            # 添加到对应分类
            $displayText = "$($app.Name),$($app.Desc)"
            if ($categoryCheckLists.ContainsKey($app.Category)) {
                 $categoryCheckLists[$app.Category].Items.Add($displayText) | Out-Null
            }
        }
        else {
            # 初始化阶段错误信息通过消息框显示
            $msg = "警告：第 $($i+1) 行格式错误（至少需4个字段），已跳过（内容：$originalLine）"
            [System.Windows.Forms.MessageBox]::Show($msg, "格式错误", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Warning)
            Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg" -ForegroundColor Yellow
        }
    }

    if ($apps.Count -eq 0) {
        throw "配置文件中未找到有效的应用程序信息"
    }
    
    Write-Host "[$(Get-Date -Format 'HH:mm:ss')] 成功加载 $($apps.Count) 个应用程序信息" -ForegroundColor Green
}
catch {
    $errorMsg = "错误: $_"
    [System.Windows.Forms.MessageBox]::Show($errorMsg, "错误", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
    Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $errorMsg" -ForegroundColor Red
    exit
}

function Get-PackageDescriptionAndUrl {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory=$true, HelpMessage="要查询的程序ID")]
        [string]$id
    )

    # 设置输出编码为 UTF-8，确保中文正常显示
    $OutputEncoding = [Console]::OutputEncoding = [System.Text.UTF8Encoding]::UTF8

    try {
        # 调试信息：记录正在查询的应用ID
        $msg = "正在查询应用信息: ID=$id"
        Add-Log $msg
        Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg" -ForegroundColor Cyan
        
        # 执行 winget 命令并捕获输出
        $output = winget show --id $Id 2>&1
        
        # 调试信息：记录winget命令的退出代码
        $msg = "winget命令退出代码: $LASTEXITCODE"
        Add-Log $msg
        Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg"
        
        # 检查命令是否执行成功
        if ($LASTEXITCODE -ne 0) {
            Write-Error "无法找到ID为 '$Id' 的程序，请检查ID是否正确。"
            $msg = "错误: 无法找到ID为 '$Id' 的程序"
            Add-Log $msg
            Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg" -ForegroundColor Red
            return $null
        }

        # 初始化变量
        $description = $null
        $installerUrl = $null

        # 循环遍历输出的每一行并提取所需的值
        foreach ($line in $output) {
            # 提取描述
            if ($line -like "*描述*") {
                $description = ($line -split ":", 2)[1].Trim()
                $msg = "提取到描述: $description"
                Add-Log $msg
                Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg"
            }
            # 提取安装程序 URL
            elseif ($line -like "*安装程序 URL*") {
                # 直接从原始行中提取 URL
                if ($line -match 'https?://\S+') {
                    $installerUrl = $Matches[0].Trim()
                    $msg = "提取到安装URL: $installerUrl"
                    Add-Log $msg
                    Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg" -ForegroundColor Green
                }
            }
        }

        # 返回结果作为自定义对象
        [PSCustomObject]@{
            Description = $description
            InstallerUrl = $installerUrl
        }
    }
    catch {
        Write-Error "查询过程中发生错误: $_"
        $msg = "查询应用信息时出错: $_"
        Add-Log $msg
        Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg" -ForegroundColor Red
        return $null
    }
}

# 全选 按钮的点击事件
$selectAllButton.Add_Click({
    $currentCategory = $tabControl.SelectedTab.Text
    $currentCheckList = $categoryCheckLists[$currentCategory]
    for ($i = 0; $i -lt $currentCheckList.Items.Count; $i++) {
        $currentCheckList.SetItemChecked($i, $true)
    }
    $msg = "已全选 $currentCategory 分类下的所有应用"
    Add-Log $msg
    Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg" -ForegroundColor Cyan
})

# 取消全选 按钮的点击事件
$unselectAllButton.Add_Click({
    $currentCategory = $tabControl.SelectedTab.Text
    $currentCheckList = $categoryCheckLists[$currentCategory]
    for ($i = 0; $i -lt $currentCheckList.Items.Count; $i++) {
        $currentCheckList.SetItemChecked($i, $false)
    }
    $msg = "已取消全选 $currentCategory 分类下的所有应用"
    Add-Log $msg
    Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg" -ForegroundColor Cyan
})

# 搜索过滤事件（输入内容时过滤列表）
$searchTextBox.Add_TextChanged({
    $searchText = $searchTextBox.Text.Trim()
    if ($searchText -eq "") { $searchText = "*" }
    
    $msg = "执行搜索过滤: $searchText"
    Add-Log $msg
    Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg"

    # 过滤所有分类选项卡中的内容
    foreach ($category in $categoryCheckLists.Keys) {
        $checkList = $categoryCheckLists[$category]
        $checkList.Items.Clear()

        # 根据当前分类筛选
        $filteredApps = if ($category -eq "全部分类") {
            $apps
        }
        else {
            $apps | Where-Object { $_.Category -eq $category }
        }

        # 应用搜索过滤
        $matchingCount = 0
        foreach ($app in $filteredApps) {
            if ($app.Name -like "*$searchText*" -or $app.Desc -like "*$searchText*") {
                $displayText = "$($app.Name),$($app.Desc)"
                $checkList.Items.Add($displayText)  | Out-Null
                $matchingCount++
            }
        }
        
        $msg = "在 $category 分类中找到 $matchingCount 个匹配项"
        Add-Log $msg
        Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg"
    }
})

# 安装按钮点击事件 - WinGet通道
$installButton.Add_Click({
    # 显示日志窗口并调整选项卡宽度
    $rightPanel.Visible = $true
    $tabControl.Size = New-Object System.Drawing.Size(550, 450)  # 缩小选项卡宽度，为日志窗口腾出空间
    
    # 收集所有选中的应用
    $selectedApps = @()
    $currentCategory = $tabControl.SelectedTab.Text
    $currentCheckList = $categoryCheckLists[$currentCategory]

    # 获取当前分类下的应用列表
    $currentApps = if ($currentCategory -eq "全部分类") {
        $apps
    }
    else {
        $apps | Where-Object { $_.Category -eq $currentCategory }
    }

    # 过滤搜索条件
    $searchText = $searchTextBox.Text.Trim()
    if ($searchText -eq "") { $searchText = "*" }
    $filteredCurrentApps = $currentApps | Where-Object {
        $_.Name -like "*$searchText*" -or $_.Desc -like "*$searchText*"
    }

    # 匹配选中项（改进版：正确处理描述中的逗号）
    for ($i = 0; $i -lt $currentCheckList.CheckedItems.Count; $i++) {
        $displayText = $currentCheckList.CheckedItems[$i].ToString()
        $firstCommaIndex = $displayText.IndexOf(',')
        
        if ($firstCommaIndex -gt 0) {
            $name = $displayText.Substring(0, $firstCommaIndex).Trim()
            $desc = $displayText.Substring($firstCommaIndex + 1).Trim()
        }
        else {
            $name = $displayText.Trim()
            $desc = ""
        }

        $matchedApp = $filteredCurrentApps | Where-Object {
            $_.Name -eq $name -and $_.Desc -eq $desc
        }
        if ($matchedApp) {
            $selectedApps += $matchedApp
        }
    }

    if ($selectedApps.Count -eq 0) {
        [System.Windows.Forms.MessageBox]::Show("请至少选择一个应用程序进行安装", "提示", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Information)
        return
    }

    # 显示确认信息
    $confirmMessage = "您确定要安装以下 $($selectedApps.Count) 个应用程序吗？`n`n"
    foreach ($app in $selectedApps) {
        $confirmMessage += "- $($app.Name)`n"
    }

    $result = [System.Windows.Forms.MessageBox]::Show($confirmMessage, "确认安装", [System.Windows.Forms.MessageBoxButtons]::YesNo, [System.Windows.Forms.MessageBoxIcon]::Question)
    if ($result -ne [System.Windows.Forms.DialogResult]::Yes) {
        return
    }

    $msg = "用户选择了 $($selectedApps.Count) 个应用程序通过WinGet通道进行安装"
    Add-Log $msg
    Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg" -ForegroundColor Cyan

    # 创建进度窗口
    $progressForm = New-Object System.Windows.Forms.Form
    $progressForm.Text = "正在安装应用程序"
    $progressForm.Size = New-Object System.Drawing.Size(500, 150)
    $progressForm.StartPosition = "CenterScreen"
    $progressForm.FormBorderStyle = "FixedDialog"
    $progressForm.MaximizeBox = $false
    $progressForm.MinimizeBox = $false

    $progressLabel = New-Object System.Windows.Forms.Label
    $progressLabel.Location = New-Object System.Drawing.Point(20, 20)
    $progressLabel.Size = New-Object System.Drawing.Size(440, 20)
    $progressForm.Controls.Add($progressLabel)

    $progressBar = New-Object System.Windows.Forms.ProgressBar
    $progressBar.Location = New-Object System.Drawing.Point(20, 50)
    $progressBar.Size = New-Object System.Drawing.Size(440, 30)
    $progressBar.Maximum = $selectedApps.Count
    $progressBar.Value = 0
    $progressForm.Controls.Add($progressBar)

    $statusLabel = New-Object System.Windows.Forms.Label
    $statusLabel.Location = New-Object System.Drawing.Point(20, 90)
    $statusLabel.Size = New-Object System.Drawing.Size(440, 20)
    $statusLabel.Text = "准备开始安装..."
    $progressForm.Controls.Add($statusLabel)

    $progressForm.Show()
    $progressForm.Refresh()

    # 按顺序安装选中的应用
    $current = 1
    foreach ($app in $selectedApps) {
        $progressLabel.Text = "正在安装: $($app.Name) ($current/$($selectedApps.Count))"
        $statusLabel.Text = "执行中，请等待..."
        $progressBar.Value = $current
        $progressForm.Refresh()

        $msg = "开始安装: $($app.Name) (ID: $($app.AppId))"
        Add-Log $msg
        Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg" -ForegroundColor Cyan

        try {
            # 执行安装命令
            $installCommand = "winget install --id $($app.AppId) --accept-source-agreements --accept-package-agreements --source winget --include-unknown"
            $msg = "执行命令: $installCommand"
            Add-Log $msg
            Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg"

            # 执行命令并获取进程信息
            $process = Start-Process cmd.exe -ArgumentList "/k title 正在安装: $($app.Name) & echo. & $installCommand & echo. & echo 安装操作已完成 & timeout /t 1 & exit" -Wait -PassThru

            $statusLabel.Text = "操作已完成"
            $msg = "$($app.Name) 安装操作已完成，退出代码: $($process.ExitCode)"
            Add-Log $msg
            Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg" -ForegroundColor Green
        }
        catch {
            $statusLabel.Text = "操作出错: $_"
            $msg = "$($app.Name) 安装过程出错: $_"
            Add-Log $msg
            Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg" -ForegroundColor Red
        }

        $current++
        $progressForm.Refresh()
        Start-Sleep -Milliseconds 500
    }

    # 完成提示
    $progressBar.Value = $progressBar.Maximum
    $progressLabel.Text = "安装操作完成"
    $statusLabel.Text = "所有选中的应用程序已处理完毕"
    $progressForm.Refresh()
    
    $msg = "所有选中的 $($selectedApps.Count) 个应用程序已处理完毕"
    Add-Log $msg
    Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg" -ForegroundColor Green
    
    Start-Sleep -Seconds 2
    $progressForm.Close()

    [System.Windows.Forms.MessageBox]::Show("所有选中的应用程序安装操作已完成`n详情请查看右侧日志和控制台输出", "操作完成", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Information)
})


# 多线程下载安装按钮点击事件（重点优化部分）
$multiThreadInstallButton.Add_Click({
    # 显示日志窗口并调整选项卡宽度
    $rightPanel.Visible = $true
    $tabControl.Size = New-Object System.Drawing.Size(550, 450)  # 缩小选项卡宽度，为日志窗口腾出空间
    
    # 收集所有选中的应用
    $selectedApps = @()
    $currentCategory = $tabControl.SelectedTab.Text
    $currentCheckList = $categoryCheckLists[$currentCategory]

    # 获取当前分类下的应用列表
    $currentApps = if ($currentCategory -eq "全部分类") {
        $apps
    }
    else {
        $apps | Where-Object { $_.Category -eq $currentCategory }
    }

    # 过滤搜索条件
    $searchText = $searchTextBox.Text.Trim()
    if ($searchText -eq "") { $searchText = "*" }
    $filteredCurrentApps = $currentApps | Where-Object {
        $_.Name -like "*$searchText*" -or $_.Desc -like "*$searchText*"
    }

    # 匹配选中项（改进版：正确处理描述中的逗号）
    for ($i = 0; $i -lt $currentCheckList.CheckedItems.Count; $i++) {
        $displayText = $currentCheckList.CheckedItems[$i].ToString()
        $firstCommaIndex = $displayText.IndexOf(',')
        
        if ($firstCommaIndex -gt 0) {
            $name = $displayText.Substring(0, $firstCommaIndex).Trim()
            $desc = $displayText.Substring($firstCommaIndex + 1).Trim()
        }
        else {
            $name = $displayText.Trim()
            $desc = ""
        }

        $matchedApp = $filteredCurrentApps | Where-Object {
            $_.Name -eq $name -and $_.Desc -eq $desc
        }
        if ($matchedApp) {
            $selectedApps += $matchedApp
        }
    }

    if ($selectedApps.Count -eq 0) {
        [System.Windows.Forms.MessageBox]::Show("请至少选择一个应用程序进行安装", "提示", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Information)
        return
    }

    # 显示确认信息
    $confirmMessage = "您确定要安装以下 $($selectedApps.Count) 个应用程序吗？`n`n"
    foreach ($app in $selectedApps) {
        $confirmMessage += "- $($app.Name)`n"
    }

    $result = [System.Windows.Forms.MessageBox]::Show($confirmMessage, "确认安装", [System.Windows.Forms.MessageBoxButtons]::YesNo, [System.Windows.Forms.MessageBoxIcon]::Question)
    if ($result -ne [System.Windows.Forms.DialogResult]::Yes) {
        return
    }

    # 同时输出到日志窗口和控制台
    $msg = "用户选择了 $($selectedApps.Count) 个应用程序进行多线程安装"
    Add-Log $msg
    Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg" -ForegroundColor Cyan

    # 创建进度窗口
    $progressForm = New-Object System.Windows.Forms.Form
    $progressForm.Text = "正在安装应用程序"
    $progressForm.Size = New-Object System.Drawing.Size(500, 150)
    $progressForm.StartPosition = "CenterScreen"
    $progressForm.FormBorderStyle = "FixedDialog"
    $progressForm.MaximizeBox = $false
    $progressForm.MinimizeBox = $false

    $progressLabel = New-Object System.Windows.Forms.Label
    $progressLabel.Location = New-Object System.Drawing.Point(20, 20)
    $progressLabel.Size = New-Object System.Drawing.Size(440, 20)
    $progressForm.Controls.Add($progressLabel)

    $progressBar = New-Object System.Windows.Forms.ProgressBar
    $progressBar.Location = New-Object System.Drawing.Point(20, 50)
    $progressBar.Size = New-Object System.Drawing.Size(440, 30)
    $progressBar.Maximum = $selectedApps.Count
    $progressBar.Value = 0
    $progressForm.Controls.Add($progressBar)

    $statusLabel = New-Object System.Windows.Forms.Label
    $statusLabel.Location = New-Object System.Drawing.Point(20, 90)
    $statusLabel.Size = New-Object System.Drawing.Size(440, 20)
    $statusLabel.Text = "准备开始安装..."
    $progressForm.Controls.Add($statusLabel)

    $progressForm.Show()
    $progressForm.Refresh()

    # 按顺序安装选中的应用
    $current = 1
    foreach ($app in $selectedApps) {
        $progressLabel.Text = "正在安装: $($app.Name) ($current/$($selectedApps.Count))"
        $statusLabel.Text = "执行中，请等待..."
        $progressBar.Value = $current
        $progressForm.Refresh()

        # 同时输出到日志窗口和控制台
        $msg = "开始安装: $($app.Name) (ID: $($app.AppId))"
        Add-Log $msg
        Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg" -ForegroundColor Cyan

        try {
            # 调试信息：记录正在处理的应用
            $msg = "=== 开始处理 $($app.AppId) 信息 ==="
            Add-Log $msg
            Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg" -ForegroundColor Yellow
            
            # 获取应用信息（包含下载URL）
            $appInfo = Get-PackageDescriptionAndUrl -id $($app.AppId)
            
            # 检查是否获取到应用信息
            if ($appInfo) {
                $msg = "成功获取应用信息 - 描述: $($appInfo.Description)"
                Add-Log $msg
                Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg"
                
                $msg = "成功获取应用信息 - 安装URL: $($appInfo.InstallerUrl)"
                Add-Log $msg
                Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg"
            }
            else {
                $msg = "警告: 未能获取 $($app.Name) 的应用信息"
                Add-Log $msg
                Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg" -ForegroundColor Yellow
                # 跳过当前应用继续处理下一个
                $current++
                continue
            }
            
            # 记录多线程安装开始
            $msg = "开始多线程安装 $($app.Name)！"
            Add-Log $msg
            Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg" -ForegroundColor Cyan
            
            # 定义下载URL
            $downloadUrl = $($appInfo.InstallerUrl)
            
            # 验证下载URL
            if (-not $downloadUrl -or $downloadUrl -notlike "http*") {
                $msg = "错误: 无效的下载URL - $downloadUrl"
                Add-Log $msg
                Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg" -ForegroundColor Red
                $current++
                continue
            }
            
            # 调用多线程下载安装函数
            $result = Invoke-DownloadAndInstall -Url $downloadUrl
            
            # 记录安装结果
            if ($result) {
                $msg = "成功: $($app.Name) 安装完毕！"
                Add-Log $msg
                Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg" -ForegroundColor Green
            }
            else {
                $msg = "失败: $($app.Name) 安装过程出现问题"
                Add-Log $msg
                Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg" -ForegroundColor Red
            }
        }
        catch {
            $statusLabel.Text = "操作出错: $_"
            $msg = "$($app.Name) 安装过程出错: $_"
            Add-Log $msg
            Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg" -ForegroundColor Red
        }

        $current++
        $progressForm.Refresh()
        Start-Sleep -Milliseconds 500
    }

    # 完成提示
    $progressBar.Value = $progressBar.Maximum
    $progressLabel.Text = "安装操作完成"
    $statusLabel.Text = "所有选中的应用程序已处理完毕"
    $progressForm.Refresh()
    
    $msg = "所有选中的 $($selectedApps.Count) 个应用程序已处理完毕"
    Add-Log $msg
    Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg" -ForegroundColor Green
    
    Start-Sleep -Seconds 2
    $progressForm.Close()

    [System.Windows.Forms.MessageBox]::Show("所有选中的应用程序安装操作已完成`n详情请查看右侧日志和控制台输出", "操作完成", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Information)
})

# 多线程下载安装函数（简化版）
function Invoke-DownloadAndInstall {
    param(
        [Parameter(Mandatory=$true)]
        [string]$Url,
        
        [Parameter(Mandatory=$false)]
        [string]$TargetDir = $PSScriptRoot  # 默认使用脚本所在目录
    )

    # 同时输出到日志和控制台
    $msg = "进入Invoke-DownloadAndInstall函数 - URL: $Url, 目标目录: $TargetDir"
    Add-Log $msg
    Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg" -ForegroundColor DarkCyan
    
    # 检查URL是否为GitHub地址，如果是则转换为加速链接
    if ($Url -match '^https?://github\.com') {
        $acceleratedUrl = $Url -replace '^https?://', 'http://oc1.yuboat.eu.org:8046/'
        $msg = "检测到GitHub URL，已转换为加速链接: $acceleratedUrl"
        Add-Log $msg
        Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg" -ForegroundColor Green
        $Url = $acceleratedUrl
    }
    
    # 从URL中提取原始文件名
    $fileName = [System.IO.Path]::GetFileName($Url)
    $outputFile = Join-Path -Path $TargetDir -ChildPath $fileName
    
    # 输出文件信息
    $msg = "提取文件名: $fileName, 完整路径: $outputFile"
    Add-Log $msg
    Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg"
    try {
        # 检查目标文件夹是否存在，不存在则创建
        if (-not (Test-Path -Path $TargetDir)) {
            $msg = "目标文件夹不存在，正在创建: $TargetDir"
            Add-Log $msg
            Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg"
            
            New-Item -ItemType Directory -Path $TargetDir | Out-Null
            
            $msg = "已创建目标文件夹: $TargetDir"
            Add-Log $msg
            Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg" -ForegroundColor Green
        }

        # 检查是否存在同名文件，存在则删除（实现覆盖功能）
        if (Test-Path -Path $outputFile) {
            $msg = "发现同名文件，正在删除: $outputFile"
            Add-Log $msg
            Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg"
            
            Remove-Item -Path $outputFile -Force
            
            $msg = "已删除同名文件: $outputFile"
            Add-Log $msg
            Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg" -ForegroundColor Green
        }

        # 仅检查脚本所在目录的aria2c.exe
        $msg = "检查脚本目录中的aria2c.exe..."
        Add-Log $msg
        Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg"
        
        # 脚本所在目录的aria2c.exe路径
        $aria2Path = Join-Path -Path $PSScriptRoot -ChildPath "aria2c.exe"
        
        # 检查是否存在aria2c.exe
        if (-not (Test-Path -Path $aria2Path -PathType Leaf)) {
            $msg = "错误: 在脚本目录未找到aria2c.exe - $aria2Path"
            Add-Log $msg
            Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg" -ForegroundColor Red
            
            throw "未找到aria2c.exe，请确保其与脚本在同一目录中"
        }
        
        $versionInfo = & $aria2Path --version | Select-Object -First 1
        $msg = "使用脚本目录中的aria2c: $aria2Path，版本信息: $versionInfo"
        Add-Log $msg
        Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg" -ForegroundColor Green

        # 使用aria2进行多线程下载
        $msg = "开始使用aria2下载文件..."
        Add-Log $msg
        Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg" -ForegroundColor Cyan
        
        # 构建aria2命令
        $aria2Command = "`"$aria2Path`" --split=16 --max-connection-per-server=8 --console-log-level=info --allow-overwrite=true --dir=`"$TargetDir`" --out=`"$fileName`" `"$Url`""
        $msg = "执行aria2命令: $aria2Command"
        Add-Log $msg
        Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg" -ForegroundColor Cyan
        
        # 执行aria2命令
        & $aria2Path `
            --split=16 `
            --max-connection-per-server=8 `
            --console-log-level=notice `
            --allow-overwrite=true `
            --dir="$TargetDir" `
            --out="$fileName" `
            "$Url" 2>&1 | ForEach-Object {
                # 将aria2的输出显示在控制台
                Write-Host "[$(Get-Date -Format 'HH:mm:ss')] [aria2] $_"
            }
        
        # 记录aria2退出代码
        $msg = "aria2命令执行完毕，退出代码: $LASTEXITCODE"
        Add-Log $msg
        Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg" -ForegroundColor Cyan

        # 检查下载是否成功
        if (-not (Test-Path -Path $outputFile)) {
            $msg = "错误: 下载失败，未找到文件: $outputFile"
            Add-Log $msg
            Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg" -ForegroundColor Red
            
            throw "下载失败，未找到文件: $outputFile"
        }
        
        # 验证文件大小
        $fileSize = (Get-Item $outputFile).Length
        $msg = "下载成功，文件大小: $fileSize 字节"
        Add-Log $msg
        Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg" -ForegroundColor Green
        
        if ($fileSize -eq 0) {
            $msg = "警告: 下载的文件大小为0字节，可能下载不完整"
            Add-Log $msg
            Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg" -ForegroundColor Yellow
            
            throw "下载的文件为空"
        }

        $msg = "开始安装程序: $outputFile"
        Add-Log $msg
        Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg" -ForegroundColor Cyan

        # 启动安装程序并等待其完成
        $installProcess = Start-Process -FilePath $outputFile -Wait -PassThru -ErrorAction Stop
        
        $msg = "安装程序退出代码: $($installProcess.ExitCode)"
        Add-Log $msg
        Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg"

        # 检查安装程序的退出代码
        if ($installProcess.ExitCode -eq 0) {
            $msg = "安装成功完成"
            Add-Log $msg
            Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg" -ForegroundColor Green
            
            return $true
        } else {
            $msg = "警告: 安装程序退出，退出代码: $($installProcess.ExitCode)"
            Add-Log $msg
            Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg" -ForegroundColor Yellow
            
            return $false
        }
    }
    catch {
        $msg = "执行过程中发生错误: $_"
        Add-Log $msg
        Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg" -ForegroundColor Red
        
        return $false
    }
}

# 退出按钮点击事件
$exitButton.Add_Click({
    $msg = "用户点击退出按钮，程序将关闭"
    Add-Log $msg
    Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg" -ForegroundColor Cyan
    $form.Close()
})

# 添加窗口加载事件，实现2秒后显示控件（修复定时器错误）
$form.Add_Load({
    # 创建定时器并存储在脚本作用域中
    $script:timer = New-Object System.Windows.Forms.Timer
    $script:timer.Interval = 1000  # 1000毫秒 = 1秒
    
    # 定义定时器事件处理
    $script:timer.Add_Tick({
        # 显示所有初始隐藏的控件
        $titleLabel.Visible = $true
        $searchPanel.Visible = $true
        $tabControl.Visible = $true
        $installButton.Visible = $true
        $multiThreadInstallButton.Visible = $true
        $exitButton.Visible = $true
        
        # 安全停止并释放定时器
        if ($script:timer) {
            $script:timer.Stop()
            $script:timer.Dispose()
            $script:timer = $null
        }
    })
    
    # 启动定时器
    $script:timer.Start()
})

# 显示主窗口
$form.ShowDialog() | Out-Null
